﻿#if UNITY_EDITOR

using System;
using UnityEditor;
using UnityEngine;


namespace AI.Graph.Editor {


    public class HistoryPanel {

#region Static

        private const string clearUnityHistoryTitle = "Clear Unity History";
        private const string clearUnityHistoryMessage = "Do you want to delete the Unity history?\nYou cannot undo this action.";

#endregion


#region Fields

        private AIGraph m_graph;
        private Action m_repaintCallback;
        private Rect m_rect;
        private Vector2 m_scrollPosition;
        private bool m_isVerticalScrollbarEnabled;
        private bool m_showUnityRecords = true;

#endregion


        public HistoryPanel (AIGraph graph, Action repaintCallback) {
            m_graph = graph;
            m_repaintCallback = repaintCallback;

            GraphUndo.onRecordsChanged -= Repaint;
            GraphUndo.onRecordsChanged += Repaint;
        }


        void Repaint () {
            m_repaintCallback.Invoke ();
        }


        public void OnGUI (Rect rect) {
            m_rect = rect;

            GUILayout.BeginArea (rect);

            DrawToolbarGUI (rect.width);

            GUILayout.BeginArea (new Rect (0, Styles.toolbarHeight, rect.width, rect.height - Styles.toolbarHeight));

            DrawHistory (rect.width, rect.height);

            GUILayout.EndArea ();
            GUILayout.EndArea ();
        }


        void DrawToolbarGUI (float width) {
            Rect rect = new Rect (0, 0, width, Styles.toolbarHeight);
            Rect toggleRect = new Rect (0, 0, 90, rect.height);
            Rect clearGraphUndoRect = new Rect (toggleRect.xMax + 1, 0, 45, rect.height);
            Rect clearAllUndoRect = new Rect (clearGraphUndoRect.xMax - 1, 0, 60, rect.height);
            Rect plusRect = new Rect (rect.width - 20 - Styles.scrollbarWidth, 0, 20, rect.height);
            Rect minusRect = new Rect (plusRect.x - 20 - 1, 0, 20, rect.height);

            EditorGUI.Toolbar (rect, false, true, false, true);

            m_showUnityRecords = EditorGUI.Toggle (toggleRect, m_showUnityRecords, "Unity Records");

            GUI.enabled = GraphUndo.hasUndo || GraphUndo.hasRedo;
            if (EditorGUI.Button (clearGraphUndoRect, "Clear")) {
                GraphUndo.Clear ();
            }

            GUI.enabled = GraphUndo.hasUnityUndo || GraphUndo.hasUnityRedo;
            if (EditorGUI.Button (clearAllUndoRect, "Clear All", Styles.clearAllButtonHoverColor)) {
                if (EditorUtility.DisplayDialog (clearUnityHistoryTitle, clearUnityHistoryMessage, "Clear", "Don't Clear")) {
                    GraphUndo.ClearAll ();
                }
            }

            GUI.enabled = GraphUndo.hasUnityUndo;
            if (EditorGUI.Button (minusRect, "<")) {
                UnityEditor.Undo.PerformUndo ();
            }

            GUI.enabled = GraphUndo.hasUnityRedo;
            if (EditorGUI.Button (plusRect, ">")) {
                UnityEditor.Undo.PerformRedo ();
            }

            GUI.enabled = true;
        }


        void DrawHistory (float width, float height) {
            string[] undo = m_showUnityRecords ? GraphUndo.unityUndoRecords : GraphUndo.undoRecords;
            string[] redo = m_showUnityRecords ? GraphUndo.unityRedoRecords : GraphUndo.redoRecords;

            float viewRectHeight = GetRecordBackgroundRect (undo.Length + redo.Length - 2).yMax;

            Rect scrollRect = new Rect (0, 0, width, height);
            Rect viewRect = new Rect (0, scrollRect.y, scrollRect.width, viewRectHeight + Styles.recordListBottomSpace + 3);
            m_isVerticalScrollbarEnabled = EditorGUIUtility.IsVerticalScrollbarEnabled (scrollRect, viewRect);
            m_scrollPosition = GUI.BeginScrollView (scrollRect, m_scrollPosition, viewRect, false, false);

            DrawRecords (undo, redo);

            GUI.EndScrollView ();
        }


        void DrawRecords (string[] undoRecords, string[] redoRecords) {
            for (int i = 0; i < undoRecords.Length; i++) {
                EditorGUI.DrawSolidTexture (GetRecordBackgroundRect (i), Styles.recordBackgroundColor.color);
                EditorGUI.Label (GetRecordLabelRect (i), undoRecords[i], EditorGUI.textStyleLeft);
            }

            GUI.enabled = false;
            for (int i = 0; i < redoRecords.Length; i++) {
                EditorGUI.DrawSolidTexture (GetRecordBackgroundRect (i + undoRecords.Length), Styles.recordBackgroundColor.color);
                EditorGUI.Label (GetRecordLabelRect (i + undoRecords.Length), redoRecords[redoRecords.Length - 1 - i], EditorGUI.textStyleLeft);
            }

            GUI.enabled = true;
        }


        Rect GetRecordBackgroundRect (int index) {
            return new Rect (
                Styles.recordBackgroundPaddingLeft,
                index * (Styles.recordHeight + Styles.recordSpace) + Styles.recordListTopSpace,
                (m_isVerticalScrollbarEnabled ? m_rect.width - Styles.scrollbarWidth : m_rect.width - 2) - Styles.recordBackgroundPaddingLeft - Styles.recordBackgroundPaddingRight,
                Styles.recordHeight);
        }


        Rect GetRecordLabelRect (int index) {
            Rect rect = GetRecordBackgroundRect (index);
            rect.x += Styles.recordLabelPaddingLeft;
            rect.width -= Styles.recordLabelPaddingLeft + Styles.recordLabelPaddingRight;
            return rect;
        }


        static class Styles {

            public static readonly Color clearAllButtonHoverColor = new Color32 (226, 38, 69, 70);
            public static readonly EditorColor recordBackgroundColor = new EditorColor (new Color32 (170, 170, 170, 255), new Color32 (48, 48, 48, 255));
            public static readonly float recordLabelPaddingLeft = 25;
            public static readonly float recordLabelPaddingRight = 15;
            public static readonly float recordBackgroundPaddingLeft = 2;
            public static readonly float recordBackgroundPaddingRight = 2;
            public static readonly float recordHeight = 21;
            public static readonly float recordSpace = 2;
            public static readonly float recordListTopSpace = 2;
            public static readonly float recordListBottomSpace = 2;
            public static readonly float toolbarHeight = 18;
            public static readonly float scrollbarWidth;


            static Styles () {
                scrollbarWidth = GUI.skin.verticalScrollbar.fixedWidth;
            }

        }

    }


}
#endif